package com.scilvet.reportcomposer.data;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

import org.apache.log4j.Logger;

import au.com.bytecode.opencsv.CSVReader;

import com.scilvet.reportcomposer.account.AccountID;
import com.scilvet.reportcomposer.account.AccountStore;
import com.scilvet.reportcomposer.account.Amount;
import com.scilvet.reportcomposer.account.MapAccountStore;
import com.scilvet.reportcomposer.exception.FileException;

public class CSVDataReader implements DataReader {
	
	// TeamSystem format column identifiers
	private static final String ACCOUNT_NUMBER_COL_ID = "Conto";
	private static final String ACCOUNT_CREDIT_COL_ID = "Avere";
	private static final String ACCOUNT_DEBIT_COL_ID = "Dare";
	private static final String ACCOUNT_BALANCE_COL_ID = "Saldo";
	
	private int accountIDCol = -1;
	private int accountCreditCol = -1;
	private int accountDebitCol = -1;
	private int accountBalanceCol = -1;
	
	private Logger logger = Logger.getLogger(CSVDataReader.class);
	
	private void loadColumnNumbers(String[] header) throws FileException {
		
		for (int i = 0; i < header.length; i ++) {
			
			if (header[i].compareTo(ACCOUNT_NUMBER_COL_ID) == 0) {
				accountIDCol = i;
				continue;
			}
			
			if (header[i].compareTo(ACCOUNT_CREDIT_COL_ID) == 0) {
				accountCreditCol = i;
				continue;
			}
			
			if (header[i].compareTo(ACCOUNT_DEBIT_COL_ID) == 0) {
				accountDebitCol = i;
				continue;
			}
			
			if (header[i].compareTo(ACCOUNT_BALANCE_COL_ID) == 0) {
				accountBalanceCol = i;
				continue;
			}
		}
		
		if (accountIDCol == -1 ||
			accountCreditCol == -1 ||
			accountDebitCol == -1 ||
			accountBalanceCol == -1) {
			throw new FileException("Missing columns in account file");
		}
	}
	
	private Amount amountFromString(String stringNumber) {
		
		if (stringNumber.isEmpty()) {
			return Amount.ZERO;
		}
		
		stringNumber = stringNumber.replace(".", "").replace(",", ".");
		
		return new Amount(stringNumber);
	}
	
	@Override
	public AccountStore loadData(String file) throws FileException {
		
		if (file == null) {
			throw new IllegalArgumentException("Illegal null argument in DataParser loadData");
		}
		
		return loadData(new File(file));
	}

	@Override
	public AccountStore loadData(File file) throws FileException {

		if (file == null) {
			throw new IllegalArgumentException("Illegal null argument in DataParser loadData");
		}
		
		AccountStore accountStore = new MapAccountStore();
		
		try {
			
			CSVReader dataReader = new CSVReader(new FileReader(file), ';');
			
			String[] line = dataReader.readNext();
			if (line == null) {
				return null;
			}
			loadColumnNumbers(line);
			
			AccountID accountID;
			Amount credit, debit, balance;
			while ((line = dataReader.readNext()) != null) {
				accountID = new AccountID(line[accountIDCol]);
				credit = amountFromString(line[accountCreditCol]);
				debit = amountFromString(line[accountDebitCol]);
				balance = amountFromString(line[accountBalanceCol]);
				accountStore.addToAccount(accountID, credit, debit, balance);
			}
			dataReader.close();
			
		} catch (FileNotFoundException e) {
			logger.error(e.getMessage());
			throw new FileException("File " + file + " not found while loading account data", e);
		} catch (IOException e) {
			logger.error(e.getMessage());
			throw new FileException("Error loading account data from file " + file, e);
		}
		
		return accountStore;
	}

}
